﻿import { store } from '@/store';
import { LogOut } from '@/store/reducerModule/userReducer';
import { getToken, removeToken } from '@/utils/auth';
import errorCode from '@/utils/errorCode';
import { message } from 'antd';

import axios from 'axios';
import { LRUCache } from 'lru-cache';

// 请求重试配置
const RETRY_COUNT = 3; // 重试次数
const RETRY_DELAY = 1000; // 重试间隔时间，单位：毫秒

// 缓存配置
const cache = new LRUCache({
  max: 100, // 缓存最大数量
  maxAge: 1000 * 60 * 5, // 缓存有效期为 5 分钟
});

// 存储每个请求的取消函数
const cancelTokens = {};

axios.defaults.headers['Content-Type'] = 'application/json;charset=utf-8';
// 创建axios实例
const service = axios.create({
  // axios中请求配置有baseURL选项，表示请求URL公共部分
  baseURL: import.meta.env.VITE_BASE_API,
  // 超时
  timeout: 60000,
});
// request拦截器
service.interceptors.request.use(
  (config) => {
    // 是否需要设置 token
    const isToken = (config.headers || {}).isToken === false;
    if (getToken() && !isToken) {
      config.headers['token'] = getToken(); // 让每个请求携带自定义token 请根据实际情况自行修改
    }
    const key = `${config.method}-${config.url}`;
    // 如果存在上一次相同请求，则取消上一次请求
    if (cancelTokens[key] && config.isCacel) {
      console.log('%%%%%%%%%%%%%%%%请求被新的相同请求取消');
      cancelTokens[key]('请求被新的相同请求取消');
    }
    // 为当前请求创建一个取消令牌
    const source = axios.CancelToken.source();
    config.cancelToken = source.token;
    // 保存当前请求的取消函数
    cancelTokens[key] = source.cancel;
    return config;
  },
  (error) => {
    Promise.reject(error);
  },
);

// 响应拦截器
service.interceptors.response.use(
  async (res) => {
    // 未设置状态码则默认成功状态
    const code = res.data.code || 200;
    // 获取错误信息
    const msg = errorCode[code] || res.data.msg || errorCode['default'];
    if (code === 401) {
      message.error(msg);
      removeToken();
      store.dispatch(LogOut);
      location.href = '/admin/#/login';
      return { code: 401, msg: msg, data: null };
    } else if (code === 500) {
      message.error(msg);
      return { code: 500, msg: msg, data: null };
    } else if (code !== 200) {
      message.error(msg);
      return { code: code, msg: msg, data: null };
    } else {
      //把字符串total 转换成 数字 total
      if (res.data.data && res.data.data.total) {
        res.data.data.total = parseInt(res.data.data.total);
      }
      return { code: 200, msg: msg, data: res.data.data };
    }
  },
  async (error) => {
    let { message: msg, config } = error;
    if (!config) return Promise.reject(error);
    const key = `${config?.method}-${config?.url}`;
    if (key) {
      // 请求出错后清除取消函数记录
      delete cancelTokens[key];
    }
    config.retryCount = config?.retryCount || 0;
    if (!config || !config.retry || config.retryCount >= RETRY_COUNT) {
      if (msg === 'Network Error') {
        msg = '后端接口连接异常';
      } else if (msg.includes('timeout')) {
        msg = '系统接口请求超时';
      } else if (msg.includes('Request failed with status code')) {
        msg = '系统接口' + msg.substr(msg.length - 3) + '异常';
      }
      message.error(msg);
      return Promise.reject(error);
    }
    config.retryCount++;
    // 设置延迟重试
    await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY));
    return service(config);
  },
);

// 封装请求函数
const request = async (options) => {
  const {
    url, // 请求地址
    method = 'get', // 请求方法
    params, // 请求参数
    data, // 请求体
    cacheKey, // 缓存key
    idempotent = false, // 幂等请求
    retry = false, // 重试
    isCacel = false, // 是否取消
  } = options;
  // 根据请求方法、url、params、data生成缓存key
  const key = cacheKey || `${method}-${url}-${JSON.stringify(params)}-${JSON.stringify(data)}`;

  // 幂等请求检查缓存
  if (idempotent) {
    const cachedResponse = cache.get(key);
    if (cachedResponse) {
      return cachedResponse;
    }
  }

  const config = {
    url,
    method,
    params,
    data,
    retry,
    isCacel,
  };

  // 发送请求
  const response = await service(config);
  // 缓存响应
  if (idempotent) {
    cache.set(key, response);
  }
  return response;
};

// 串行请求函数
const sequentialRequests = async (requests) => {
  const results = [];
  for (const req of requests) {
    try {
      const result = await request(req);
      results.push(result);
    } catch (error) {
      results.push(error);
    }
  }
  return results;
};

// 并发请求函数
const concurrentRequests = async (requests) => {
  // 并发请求
  const promises = requests.map((req) => request(req));
  // 等待所有请求完成
  return Promise.allSettled(promises);
};

// 竞态处理
const raceConditionHandler = (() => {
  // 创建锁对象
  const locks = {};
  return {
    // 请求函数
    makeRequest: async (options) => {
      const { url } = options;
      // 检查是否有其他请求正在处理相同资源
      if (locks[url]) {
        await locks[url];
      }
      let resolveLock;
      // 创建锁
      locks[url] = new Promise((resolve) => {
        resolveLock = resolve;
      });
      try {
        // 发送请求
        const result = await request(options);
        return result;
      } finally {
        // 释放锁
        resolveLock();
        delete locks[url];
      }
    },
  };
})();

export { request, sequentialRequests, concurrentRequests, raceConditionHandler };
export default service;
